package cn.edu.neu.lab603

import breeze.linalg._
import cn.edu.neu.lab603.math.{DCRank, PageRank, ResRank}
import org.scalatest.FunSuite

/** 网络链路分析。
  *
  * Created by yfwz100 on 2016/10/10.
  */
class LinkAnalysis extends FunSuite {

  import math.NetworkHelper._

  ignore("for 10 nodes") {
    val network = DenseMatrix(
      (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
      (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
      (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
    )

    testRank(network)
  }

  test("for 11 nodes.") {
    val network = DenseMatrix(
      (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
      (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
      (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
      (1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
    )

    testRank(network)
  }

  test("for 20 nodes with 12 connected nodes") {
    val links = network(20)
    links.addEdge(1, 9)
    links.addEdge(2, 9)
    links.addEdge(3, 9)
    links.addEdge(4, 9)
    links.addEdge(5, 9)

    links.addEdge(10, 12)
    links.addEdge(10, 13)
    links.addEdge(10, 14)

    links.addEdge(11, 15)
    links.addEdge(16, 15)

    links.addEdge(17, 18)
    links.addEdge(19, 18)

    testRank(links)
  }

  test("for 200 nodes with 12 connected nodes") {
    val links = network(200)
    links.addEdge(1 <-> 9)
    links.addEdge(2 <-> 9)
    links.addEdge(3 <-> 9)
    links.addEdge(4 <-> 9)
    links.addEdge(5 <-> 9)

    links.addEdge(5 <-> 10)

    links.addEdge(10 <-> 12)
    links.addEdge(10 <-> 13)
    links.addEdge(10 <-> 14)

    links.addEdge(11 <-> 15)
    links.addEdge(16 <-> 15)

    links.addEdge(17 <-> 18)
    links.addEdge(19 <-> 18)

    testRank(links)
  }

  test("for 2000 nodes with 12 connected nodes") {
    val links = network(2000)
    links.addEdge(1 <-> 9)
    links.addEdge(2 <-> 9)
    links.addEdge(3 <-> 9)
    links.addEdge(4 <-> 9)
    links.addEdge(5 <-> 9)

    links.addEdge(10 <-> 12)
    links.addEdge(10 <-> 13)
    links.addEdge(10 <-> 14)

    links.addEdge(11 <-> 15)
    links.addEdge(16 <-> 15)

    links.addEdge(17 <-> 18)
    links.addEdge(19 <-> 18)

    testRank(links)
  }

  test("DCRank with res") {
    val res = DenseMatrix(
      //           0    1    2    3    4    5    6    7    8     9    10    11    12    13   14   15   16   17   18   19
      /* cpu */ (0.8, 0.3, 0.2, 0.2, 0.5, 0.5, 0.7, 0.6, 0.6, 0.10, 0.01, 0.02, 0.01, 0.01, 0.1, 0.7, 0.3, 0.5, 0.9, 0.2),
      /* ram */ (0.5, 0.3, 0.3, 0.7, 0.8, 0.6, 0.7, 0.5, 0.3, 0.06, 0.01, 0.02, 0.01, 0.01, 0.1, 0.6, 0.5, 0.6, 0.5, 0.3),
      /* bw  */ (0.9, 0.2, 0.7, 0.6, 0.4, 0.5, 0.5, 0.5, 0.5, 0.20, 0.01, 0.01, 0.01, 0.01, 0.1, 0.2, 0.5, 0.7, 0.4, 0.2)
    )
    val s = ResRank(res)
    println((0 until res.cols).map(p => f"$p%5d").mkString(","))
    println(s.map(p => f"$p%2.3f").toArray.mkString(","))

    val links = network(20)
    links.addEdge(1, 9)
    links.addEdge(2, 9)
    links.addEdge(3, 9)
    links.addEdge(4, 9)
    links.addEdge(5, 9)

    links.addEdge(10, 12)
    links.addEdge(10, 13)
    links.addEdge(10, 14)

    links.addEdge(11, 15)
    links.addEdge(16, 15)

    links.addEdge(17, 18)
    links.addEdge(19, 18)

    testRank(links, s)
  }

  def testRank(network: DenseMatrix[Double], res: DenseVector[Double] = null): Unit = {
    // 如果 res 存在则利用 dr 和 dr+res 来比较
    val pr = if (res == null) PageRank(network) else DCRank(network)
    val dr = DCRank(network, res)
    //    println("VM: PR       DR")
    for (i <- 0 until network.rows) {
      //      println(f"$i%2d: ${pr(i)}%1.3f ${dr(i)}%1.3f")
      println(f"${dr(i)}%1.3f")
    }
  }

}
